home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / CIS_GAME.ARJ / QMATH1.THD < prev    next >
Text File  |  1993-06-25  |  65KB  |  1,498 lines

  1. _____________________ Subj: Point-to-Point 2d Geometry _____________________
  2.  
  3. Fm: MIKE ROBEL 76446,1444                      # 173935 
  4. To: Anyone                                     Date: 01-Jun-92  22:25:39
  5.  
  6. I am working on a program, and I need a line to compute the bearing from my
  7. position to a target where I am at x,y and the target is at x1,y1.  I tried
  8. using cotanget times the (x-x1)/(y-y1) but it only gives me a reading in 90
  9. degrees, with a +/- depending on whether or not the position of the other
  10. object is left, right, up, or down.  rembering my trig, that makes sense
  11. since i think tangents only go to 90 degrees, but is there any easy way to do
  12. this and get bearings from 0 to 360 degrees.
  13.  
  14. Right now I am working this in quickbasic.
  15.  
  16. Mike
  17. ...........................................................................
  18.  
  19. Fm: hercules/Assoc. SysOp 75300,3472           # 173977 
  20. To: MIKE ROBEL 76446,1444 (X)                  Date: 02-Jun-92  00:39:19
  21.  
  22. Using your notation that you are at [x,y] and the target is at [x1,y1], the
  23. bearing to the target is arc-tangent [(y1-y)/(x1-x)], the result can be
  24. evaluated either in degrees or in radians. (It's ok to use arc-cotangent as
  25. in your example.)
  26.  
  27. There are 4 cases to check:
  28.  
  29. a) if (y1-y) and (x1-x) are both positive, then the bearing is between 0 to
  30. 90 degrees.
  31.  
  32. b) if (y1-y) is positive but (x1-x) is negative, the the bearing is between
  33. 90 to 180 degrees.
  34.  
  35. c) if (y1-y) is negative but (x1-x) is positive, then the bearing is between
  36. 180 to 270 degrees. 
  37.  
  38. d) if (y1-y) and (x1-x) are both negative, then the bearing is between 270 to
  39. 360 degrees. 
  40.  
  41. What this means is that you need to add a multiple of 90 degrees to the angle
  42. that you get from the arc-tangent. The value of the multiple is controlled by
  43. the outcome of the four conditions.
  44.  
  45. There are probably better ways/algorithms to do this. I'm a lousy programmer.
  46.  
  47. _____________________ Subj: Point-to-Line 2d Geometry _____________________
  48.  
  49. Fm: KGliner 70363,3672                         # 320438
  50. To: all                                        Date: 25-Mar-93  18:27:32
  51.  
  52. Given a point at coordinates Px,Py, and a line segment with the endpoints
  53. X1,Y1 and X2,Y2, how does one find the closest distance between the point
  54. and the line segment?
  55.  
  56.    Kevin
  57. ...........................................................................
  58.  
  59. Fm: Hans Peter Rushworth 100031,473            # 320619
  60. To: KGliner 70363,3672 (X)                     Date: 25-Mar-93  21:50:17
  61.  
  62. I don't have a formula offhand, but I can tell you how to work it out with a
  63. little algebra on your part. The closest point will be either (X1,Y1) or
  64. (X2,Y2) or the point (Ix,Iy) in between that forms a right angle between the
  65. line from that point to (Px,Py), and the original line segment.
  66.  
  67. Any point on the line bewteen points (X1,Y1) and (X2,Y2) can be expressed
  68. like this:
  69.  
  70.     Ix = X1 + a*(X2-X1) ---(1)
  71.     Iy = Y1 + a*(Y2-Y1) ---(2)
  72.  
  73. The value "a" is a paramter and will be between 0 and 1. If it is greater
  74. than or equal to 1 then the closest point is (X2,Y2). If it is less than or
  75. equal to zero, then the closest point is (X1,Y1). Thats the trivial solution.
  76.  
  77.  So how do you find "a"? Remember dot product of vectors? The dot product of
  78. two vectors is 0 if the angle between them is 90 degrees. The vectors in
  79. question are: [X2-X1,Y2-Y1] and [Px-Ix,Py-Iy]. The dot product of the vectors
  80. is (X2-X1)*(Px-Ix) + (Y2-Y1)*(Py-Iy) = 0. ---(3)
  81.  
  82. That is not enough for a solution, since that is true for any point that lies
  83. on the line (PxIx,PyIy). You need to substitute the equations (1),(2) above
  84. for Ix and Iy (which are in terms of the parameter a) into equation (3). If
  85. you solve this you will get a value for a. Now see if a is in the range 0-1
  86. and if so substitute it back into the equations (1) and (2), and this should
  87. give the result. Neat Huh? <g> 
  88.  
  89. Hope that helps (and is right!)
  90.  
  91. Peter.
  92. ...........................................................................
  93.  
  94. Fm: Hans Peter Rushworth 100031,473            # 320627
  95. To: Hans Peter Rushworth 100031,473 (X)        Date: 25-Mar-93  22:03:00
  96.  
  97. Again I misread the question !
  98.  
  99. Once you have the point Ix,Iy, it is a simple matter to work out the distance
  100. using the formula:
  101.  
  102.  distance = sqrt((Px-Ix)*(Px-Ix) + (Py-Iy)*(Py-Iy))
  103.  
  104. Substuting Ix & Iy with X1,Y1 or X2,Y2 if a is not in between 0 and 1.
  105.  
  106. Peter.
  107. ...........................................................................
  108.  
  109. Fm: Bob Provencher/GD SL 71621,2632            # 320949
  110. To: KGliner 70363,3672 (X)                     Date: 26-Mar-93  13:45:38
  111.  
  112. Kevin -
  113.  
  114. Let's see, if you can't project the point onto the line segment, then the
  115. shortest distance should be the min of the distance to the two end points.
  116.  
  117. If you can project the point orthogonally onto the line, then the shortest
  118. distance should be the distance to the projection point.
  119.  
  120. If Pete's method doesn't work out, I'll see if I can work this out.
  121.  
  122. Bob
  123. ...........................................................................
  124.  
  125. Fm: rod lentz 71163,57                         # 338584 
  126. To: John Dlugosz [ViewPoint] 70007,4657        Date: 20-Apr-93  23:22:41
  127.  
  128. >> how the cos (atan ()) helps you find distance?
  129.  
  130.     Ok; pixture in 2d space the two points you want to find the
  131. distance of.  Picture a right triangle connected to it, where
  132. the other 2 sides are parallel to the x & y axes, and the
  133. distance you're after is the hypotenuse.
  134.     Given the ratio of the non-hypotenuse sides of a right
  135. triangle atan() returns the angle.  The two "sides" you use are
  136. the separate distances in the x & y directions.
  137.     Do some swapping of x & y, so that your value is always in the
  138. range 0..1, i.e. (minor axis / major axis).  Index your table by
  139. (table size * minor axis / major axis).
  140.     Now cos() of the angle from the atan() is the ratio of the
  141. length along the major axis to the length of the hypotenuse.
  142.     Of course, making a table of cos(atan()) is the fastest way
  143. to go, rather than 2 separate tables.
  144.     Hope that was clear enough !
  145.  
  146.         - Rod
  147. ...........................................................................
  148.  
  149. Fm: Vu Truong (Siliconis) 70242,3015           # 369363 
  150. To: Lary Myers 76004,1574 (X)                  Date: 05-Jun-93  01:00:35
  151.  
  152. I hope this equation helps (its from my calculus book!)
  153.  
  154. | = Absolute Bar ^ = Raise to the Power of
  155.  
  156. D= (|ax0+by0+C|)/(sqr(a^2+b^2))
  157.  
  158. Distance from point (x0,y0) to line (ax+by+c=0).
  159. ...........................................................................
  160.  
  161. Fm: Bob Provencher/GD SL 71621,2632            # 369473 
  162. To: Lary Myers 76004,1574 (X)                  Date: 05-Jun-93  09:30:09
  163.  
  164. Hi Lary,
  165.  
  166. If the point normal to the line (that the line segment is part of) intersects
  167. the line segment <whew> then the intersection to the line segment is the
  168. same as the intersection to the line.  Otherwise, it would be the closest
  169. end-point.  If that's not enough to go on, I'll work out the equations.
  170.  
  171. Bob
  172.  
  173. ______________________________ Subj: 3d to 2d ______________________________
  174.  
  175. Fm: KGliner 70363,3672                         # 283627 
  176. To: all                                        Date: 22-Jan-93  16:18:27
  177.  
  178.    I've been doing some 3d work lately, and I've run into some problems
  179. projecting a point in 3d to a point in 2d.  Normally this isn't difficult,
  180. but I'm having trouble accounting for the horizon.
  181.  
  182.    What I've got are the offset coordinates in 3d for the point relative to
  183. the center of the 'view'. I also know the distance to the horizon (ie. where
  184. it collapses to nothing). Without the horizon factored in, I could just take
  185. the x and y coordinates and use those as is.  With the horizon, I need to
  186. scale them depending on the depth (the z coord).  I tried using a linear
  187. scaling method (eg. if z is 1/2 the horizon, then reduce x and y by 50%).
  188. That produces values that are sometimes close (depending on the distance of
  189. the horizon), but incorrect.
  190.  
  191.   Anyways, my trig is rusty and I've completely forgotten calculus and all
  192. that matrix stuff.  Any help on this would be much appreciated.
  193. ...........................................................................
  194.  
  195. Fm: John Burkhard 71044,3263                   # 283746 
  196. To: KGliner 70363,3672 (X)                     Date: 22-Jan-93  19:40:37
  197.  
  198. Scaling isn't all that complicated.  You were kind of on the right track. If
  199. you have two points, call the first the eye point, and the second the focal
  200. point, you compute the distance from the eyepoint to the focal point, and use
  201. that in computing the 2d positions of your 3d points.  Like:
  202.  
  203.   E = eye point
  204.   F = focal point
  205.   P = some arbitrary point
  206.  
  207.   |F| = distance between E and F (could be called the focal length)
  208.   |P| = distance from E to P
  209.  
  210.   P.x = P.x * |F| / |P|
  211.   P.y = P.y * |F| / |P|
  212.  
  213.  
  214. The closer you make F to E, the quicker things will shrink as they approach
  215. the horizon, and the farther away F is from E, the slower they shrink as they
  216. approach the horizon.  For your application, you know the distance to the
  217. horizon, so you can select your |F| to be such that stuff becomes scaled too
  218. small for display at the desired distance away.
  219. ...........................................................................
  220.  
  221. Fm: John Burkhard 71044,3263                   # 285095 
  222. To: KGliner 70363,3672 (X)                     Date: 24-Jan-93  18:27:54
  223.  
  224. >> How do I remove the distortion when up close to objects in my field of
  225. view? (ie. if I have a string of points that constitute a straight line in
  226. 3d, I want to them to retain that straightness in 2d). <<
  227.  
  228. The method I presented is the same method used when ray tracing.  Distortion
  229. is an inevitable artifact of this process.  If you want to have a distortion
  230. free scaling, you could try the following:  (this one's off the top of my
  231. head, so bear with me...)
  232.  
  233.   Single Point Perspective:
  234.  
  235.   Given H.z, the distance from the focal plane (z=0) to the horizon, the x
  236.   and y components of an arbitrary point P will both be proportional to the
  237.   distance from the horizon at which P lies.
  238.  
  239.   So:
  240.     P'.x = P.x * ( H.z - P.z ) / H.z
  241.     P'.y = P.y * ( H.z - P.z ) / H.z
  242.  
  243.   Where:
  244.     0 <= P.z <= H.z
  245.  
  246.  
  247. When P.z is 0, the point is on the focal plane, and will show at 100% scale.
  248. As P moves closer to H.z, it will be scaled linearly until P.z = H.z, at
  249. which time both the x and y components will map to 0.
  250.  
  251. Two point and three point perspective are both a little more complex.  I
  252. haven't worked out the math on them yet, but it should be an interesting
  253. exercise.
  254. ...........................................................................
  255.  
  256. Fm: KGliner 70363,3672                         # 287196 
  257. To: all                                        Date: 28-Jan-93  02:57:38
  258.  
  259. Well, those 3d to 2d projection formulas seem to work pretty well.  Now I'm
  260. stuck on what I think is a bug in the rotation-translation portion of my
  261. code. 
  262.  
  263. In a nutshell, I'm trying to translate the 3d global coordinates of a point
  264. to the 3d local coordinate system of the 'viewer'.  I've been using a sort of
  265. hacked together arctangent table (using the slope of the line between the two
  266. points) and that works-- to a point (no pun intended).  But I'm getting a
  267. slight distortion in my numbers so that when I connect a line between several
  268. points that were linear in the global coordinate system now appear just
  269. barely non-linear in the local coordinate system. 
  270.  
  271. I've been pouring over the Lee Adams books (High Performance CAD graphics in
  272. C and Visualization Graphics in C), but he's got so many variables without
  273. clear explanation it's been difficult for me to pick out the parts I'm
  274. looking for.  I did notice that an arctangent call was unnecessary, and that
  275. I had to change my numbers slightly depending on what the angle was (ie. <
  276. 90, between 90 and 180, etc-- something I already do).  But I got lost after
  277. that.  
  278.  
  279.   Any suggestions?
  280.  
  281.   Thanks,   Kevin
  282. ____________________________ Subj: more 3d to 2d ____________________________
  283.  
  284. Fm: KGliner 70363,3672                         # 287699 
  285. To: John Burkhard 71044,3263                   Date: 28-Jan-93  23:09:51
  286.  
  287. John (and Bob)-  What I have is are the coordinates (Px,Py,Pz) of a point in
  288. a global 3d coordinate system.  I also have the coordinates of the 'viewer',
  289. or camera, from which this point is being viewed (we'll call these
  290. coordinates Vx,Vy,Vz).  In addition, I have the global XY, XZ, and YZ angles
  291. that the camera is oriented.
  292.  
  293.    What I want to be able to do is find the coordinates of the point P in the
  294. camera's local 3d coordinate system (where the camera sits at 0,0,0). The
  295. next step is to project it onto a 2d screen, but I've already got that part
  296. working (your earlier formula worked great for that). 
  297.  
  298.    The overall goal here is to display a virtual 3d environment from any
  299. location and view within it (something I have already achieved, but not with
  300. the exact precision I want-- hence this question). 
  301.    Thanks,
  302.    Kevin
  303. ...........................................................................
  304.  
  305. Fm: Bob Provencher/GD SL 71621,2632            # 288055 
  306. To: KGliner 70363,3672 (X)                     Date: 29-Jan-93  18:36:26
  307.  
  308. Hi Kevin -
  309.  
  310. If you want the co-ordinates of the point (Px,Py,Pz) relative to the viewer
  311. at (Vx,Vy,Vz) then it's (Px-Vx,Py-Vy,Pz-Vz) (call it Rx,Ry,Rz).
  312.  
  313. Projecting the point onto the viewer screen can be done by scaling...
  314. Assuming +Z is into the screen, +Y is from the bottom to the top, and +X is
  315. from left to right (all co-ordinates are relative to the viewer), and Z1 is
  316. the distance from the viewer to the screen.  The the X and Y coordinates of
  317. the point on the screen (relative to the center) are given by:
  318.  
  319. X = Rx * Z1/Rz
  320. Y = Ry * Z1/Rz
  321.  
  322. In the same units that X,Y,Z were originally in.
  323.  
  324. I just came up with all this stuff off of the top of my head, so it may be
  325. completely wrong for all I know <g>.
  326.  
  327. Bob
  328. ...........................................................................
  329.  
  330. Fm: Bob Provencher/GD SL 71621,2632            # 289651 
  331. To: KGliner 70363,3672 (X)                     Date: 01-Feb-93  12:35:02
  332.  
  333. Hi Kevin -
  334.  
  335. Sorry I couldn't remember the 2D matrix rotation stuff off the top of my
  336. head the other day.  It's been a little while since I used it.
  337.  
  338. I'm pulling this stuff straight out of one of my graphics book, in this case
  339. it's "Computer Graphics, A Programming Approach," by Steven Harrington,
  340. McGraw-Hill, 1987, ISBN 0-07-026753-7.
  341.  
  342. The rotation transformation matrix, R, for rotation counterclockwise
  343. w degrees, about the point ( 0, 0 ) is:
  344.  
  345. R = | cos w  -sin w |
  346.     | sin w   cos w |
  347.  
  348. To compute the co-ordinates of a point p = ( x, y ) after rotation, you do
  349. matrix multiplication on the point with R:
  350.  
  351. p' = | x y | |  cos w  sin w | = | x cos w + y -sin w   x sin w y cos w |
  352.              | -sin w  cos w |
  353.  
  354. p' = ( x * cos(w) ) + ( y * -sin(w) ), ( x * sin(w) ) + ( y * cos(w) )
  355.  
  356. For example, rotating ( 1, 0 ) +90 degrees:
  357.  
  358. p' = ( 1 * cos(90) ) + ( 0 * -sin(90) ), ( 1 * sin(90) ) + ( 0 * cos(90) )
  359. p' = ( 0 ) + ( 0 ), ( 1 ) + ( 0 )
  360. p' = 0, 1
  361.  
  362. rotating ( 1, 0 ) 45 degrees:
  363.  
  364. p' = ( 1 * cos(45) ) + ( 0 * -sin(45) ), ( 1 * sin(45) ) + ( 0 * cos(45) )
  365. p' = ( 0.707 ) + ( 0 ), ( 0.707 ) + ( 0.525 )
  366. p' = 0.707, 0.707
  367.  
  368. rotating ( 0, 1.414 ) -45 degrees:
  369.  
  370. p' = ( 0 ) + ( 1.414 * -sin(-45) ), ( 0 ) + ( 1.414 * cos(-45) )
  371. p' = ( 0 ) + ( 1.414 * 0.707 ), ( 0 ) + ( 1.414 * 0.707 )
  372. p' = 1, 1.
  373.  
  374. If you use a lookup table, it seems to me that the equation for p' can be
  375. computed moderately fast.
  376.  
  377. Hope this helps
  378.  
  379. Bob
  380. ...........................................................................
  381.  
  382. Fm: John Burkhard 71044,3263                   # 289904 
  383. To: KGliner  70363,3672 (X)                    Date: 01-Feb-93  20:26:50
  384.  
  385. The mathematics for performing the translate and rotation in 3d are:
  386.  
  387. Given:
  388.  
  389.    Q is the point to be translated and rotated;
  390.    Q' is the result;
  391.    T is the translation offset;
  392.    r = roll angle;
  393.    p = pitch angle;
  394.    y = yaw angle;
  395.  
  396.    And
  397.  
  398.    R is the roll rotation matrix
  399.    P is the pitch rotation matrix
  400.    Y is the yaw rotation matrix
  401.  
  402. Then:
  403.  
  404.    P' = R * P * Y * (Q-T)
  405.  
  406. Where:
  407.  
  408.    Q, Q', T are of the form ( x, y, z )
  409.  
  410.    And where:
  411.  
  412.    R = +-                        -+
  413.        |  cos r   -sin r  0       |
  414.        |  sin r   cos r   0       |
  415.        |  0       0       1       |
  416.        +-                        -+
  417.  
  418.    P = +-                        -+
  419.        |  1       0       0       |
  420.        |  0       cos p   -sin p  |
  421.        |  0       sin p   cos p   |
  422.        +-                        -+
  423.  
  424.    Y = +-                        -+
  425.        |  cos y   0       -sin y  |
  426.        |  0       1       0       |
  427.        |  sin y   0       cos y   |
  428.        +-                        -+
  429.  
  430.    The ROLL angle is the angle to rotate about the Z axis;
  431.    The PITCH angle is the angle to rotate about the X axis;
  432.    And the YAW angle is the angle to rotate about the Y axis.
  433.  
  434. There are ways to write the above which eliminates floating point math
  435. entirely; only addition, subtraction, multiplication, division and square
  436. root.  
  437.  
  438. HTH,
  439.  
  440. -jb
  441.  
  442. ________________________  Subj: 3d Rotations _____________________________
  443.  
  444. ( see also the "Flights of Fantasy" thread(s) )
  445.  
  446. Fm: Mark Betz/GD SL 76605,2346                 # 199351 
  447. To: Peter Rushworth 100112,1532 (X)            Date: 12-Aug-92  23:10:18
  448.  
  449. We've run into a problem with the translation routines that handle moving the
  450. aircraft through 3 space. The method we're using starts out with an imaginary
  451. point x = 0, y = 0, z = distance travelled. This imaginary point assumes you
  452. have zero rotation relative to the world coordinate system, and are
  453. travelling along the z-axis (straight into the screen in our system). We then
  454. put the point through the following rotations, feeding the results of each
  455. into the next. The dX, dY, and dZ symbols refer to your actual rotation
  456. angles relative to the world axes, not the presumed 0 rotation angle implied
  457. by the imaginary starting point...
  458.  
  459. Z rotation: X' = (X*COS(dZ)) - (Y*SIN(dZ))
  460.             Y' = (X*SIN(dZ)) + (Z*COS(dZ))
  461.             Z' = Z
  462.  
  463. X rotation: X' = X
  464.             Y' = (Y*COS(dX)) - (Z*SIN(dX))
  465.             Z' = (Y*SIN(dX)) + (Z*COS(dX))
  466.  
  467. Y rotation: X' = (Z*SIN(dY)) + (X*COS(dY))
  468.             Y' = Y
  469.             Z' = (Z*COS(dY)) - (X*SIN(dY))
  470.  
  471. XPos += X';  YPos += Y'; ZPos += Z';
  472.  
  473. The last three statements translate your position back out to your starting
  474. point, and then add in the new deltas for the three axes.
  475.  
  476. The problem is that we're getting the right values for change along each
  477. axis, but we're getting the wrong sign for various components, depending on
  478. the rotations. For example. going into this with the view rotated to look NE,
  479. if we feed in values which should cause the plane to move directly forward,
  480. we slide left along a line bisecting the wing, because X is getting smaller
  481. when it should be getting larger. So far the only way I can think of to
  482. correct the problem is to test the rotations going in, and apply some sign
  483. changes based on whatever rules I can discover. I can't help thinking that
  484. we're missing something, though, and that we shouldn't have to flip signs
  485. explicitly. Any ideas or suggestioins you might have would be greatly
  486. appreciated. If it's my turn to initiate the transatlantic phone call say the
  487. word <g>. 
  488.                                                         --Mark
  489.  
  490. __________________________ Subj: more 3d Rotations __________________________
  491.  
  492. Fm: Chris Lampton [GAMPUB] 76711,301           # 371227 
  493. To: All                                        Date: 08-Jun-93  00:08:46
  494.  
  495. Okay, folks, I have a math question. It probably has a simple answer, but the
  496. question itself is rather difficult to express. Here's my best shot:
  497.  
  498. I have an infinite plane defined in terms of two pieces of information: the
  499. normal of the plane and an arbitrary reference point somewhere on the plane.
  500. The normal is represented as a unit vector -- call it {nx,ny,nz} -- and the
  501. reference point as a set of x,y,z coordinates. (Call these rx,ry,rz.) I also
  502. know the x,y,z coordinates of a second point on the plane. (Call it px,py,pz)
  503.  
  504. What I want to do is rotate the plane around the reference point into a new
  505. orientation, which would have a normal of {nx',ny',nz'}. (Specifically, I
  506. want to rotate it to {0,0,1}, which would make it parallel to the x,y plane.)
  507. The question is, how do I calculate the rotated coordinates (call them
  508. px',py',pz') of the point at px,py,pz, the second point on the plane? Seems
  509. like this should be easy to do, since the elements of the unit normal vectors
  510. appear to correspond to the sines and cosines of the rotations of the normal
  511. in the x,y, y,z and x,z planes. But I'm not quite sure how to get from one
  512. normal to another, i.e. how to figure the sine and cosine of the _difference_
  513. between the two normals so I can use them to rotate the point from one to the
  514. other. The arccos and arcsin might come in handy -- I could use them to
  515. calculate the angles, then subtract the angles and perform the standard
  516. rotation operations on the point using the difference in the angles -- but I
  517. have a suspicion that there's a simpler way, since I already seem to _have_
  518. the sines and cosines in the unit vectors. Should I subtract {nx,ny,nz} from
  519. {nx',ny',nz'} or vice versa? (This doesn't seem to work.) Take the dot
  520. product of the vectors? (This doesn't either.) Perform some other obscure
  521. vector operation? <g> Any suggestions? 
  522.  
  523. Clear as mud, right? But I'm sure somebody out there will understand what the
  524. heck I'm talking about. Hey, Pete...!
  525.  
  526. --Chris
  527. ...........................................................................
  528.  
  529. Fm: Hans Peter Rushworth 100031,473            # 372011 
  530. To: Chris Lampton [GAMPUB] 76711,301 (X)       Date: 08-Jun-93  23:21:15
  531.  
  532. Chris,
  533.  
  534. >> What I want to do is rotate the plane around the reference point into a
  535. new orientation, which would have a normal of {nx',ny',nz'}.
  536.  
  537. This is a three step process
  538.  
  539. Step 1: Translate the plane 1 so it's reference point is at the origin, Step
  540. 2: Rotate to align the normals Step 3: Translate back out to the reference
  541. point 
  542.  
  543. Now combine these three transformations (by matrix multiplication) to get a
  544. single transformation that does everything in one go.
  545.  
  546. I'll assume steps 1 and 3 are no problem. Doing them allows you to do step 2
  547. more easily. Onto step 2, finding a transform to align the normals...
  548.  
  549. You could solve this using a standard transformation that rotates about an
  550. arbitrary axis a certain number of degrees. The axis would be defined by the
  551. cross product of the two normal vectors, and the angle is found using the dot
  552. product of the two normal vectors. The transform you can derive using
  553. quaternions. But I'll skip the working and just give you the result:
  554.  
  555.   c@ is cos of the angle, s@ is sine of the angle
  556.   and a,b,c are the x,y,z components of the unit length cross product vector
  557.  
  558.  [ (a*a + c@*(1-a*a))   (a*b*(1-c@)-c*s@)   (a*c*(1-c@) + b*s@) ]
  559.  [ (a*b*(1-c@)) + c*s@) (b*b + c@*(1-b*b))  (b*c*(1-c@) - a*s@) ]
  560.  [ (a*c*(1-c@)) - b*s@) (c*b*(1-c@)+a*s@)   (c*c + c@*(1-c*c))  ]
  561.  
  562. This may look complex, but actually there is a pattern and there are several
  563. simplifications, particularly cos(theta) and sin(theta) which can be found
  564. from:
  565.  
  566.   cos(@) = a.b  (a,b here are unit length plane normals)
  567.   sin(@) = axb/n (n is the unit length vector, normal to a and b)
  568.  
  569. So no trig is needed!
  570.  
  571. I have never had the need to use this transform, which is the result of
  572. considerable paper calculation using quaternions, so it's possible there is
  573. an error, and the above result differs in one sign from that published in
  574. F&VD (page 227 2nd Ed), which you should consult for more information.
  575. ...........................................................................
  576.  
  577. Fm: Hans Peter Rushworth 100031,473            # 372040 
  578. To: Hans Peter Rushworth 100031,473 (X)        Date: 09-Jun-93  00:21:15
  579.  
  580. I would add that there is probably a *much more direct* way of obtaining the
  581. rotation matrix transform of step 2, but that would require more thought and
  582. scribbling, and take longer to explain.
  583.  
  584. Also I would caution you that a plane normal and one point only describe a
  585. plane, and not the points on the plane. The procedure I outlined does not
  586. take into consideration any rotation of the planes about the surface normal.
  587. it simply aligns the normals so the planes are parallel. You might have to
  588. perform an intermediate rotation step (step 2.5) to align the planes in some
  589. special way depending on the nature of the problem.
  590.  
  591. ______________________ Subj: Union of >1 Rectangles _________________________
  592.  
  593. Fm: Lutz Kretzschmar 100023,2006               # 372221 
  594. To: all                                        Date: 09-Jun-93  09:17:35
  595.  
  596. Hi all,
  597.  
  598. I have a programming problem at the moment and think this is the right place
  599. to ask.
  600.  
  601. I have a number of rectangles that may, or may not, overlap. I need to reduce
  602. this to a minimum number of non-overlapping rectangles. This is for a sort of a
  603. window manager. I keep track of what window regions need to be updated, and
  604. then blit from a virtual screen that contains the whole screen in its correct
  605. state to the actual display. Unfortunately, it's not feasable to just blit
  606. the whole thing over. So I'm looking for an algorithm that will minimize this
  607. time. 
  608.  
  609. Maybe a scanline-based edge intersection list would be a better algorithm,
  610. does anyone have experience with this? I was thinking that I could maintain a
  611. sorted list of edges per scanline, and eliminate or add edges as they appear
  612. during addition of new rects. Then blit scanline by scanline, using the edges
  613. in the list as boundaries.
  614. ...........................................................................
  615.  
  616. Fm: Mark Betz/Ass't SysOp 76605,2346           # 372715 
  617. To: Lutz Kretzschmar 100023,2006 (X)           Date: 09-Jun-93  22:07:57
  618.  
  619. Hi, Lutz. I'm not sure I understand the problem completely, but your message
  620. prompted a few thoughts. First, I'm not sure what you mean by "minimum number
  621. of non-overlapping rectangles". I'm assuming for the moment that you want to
  622. find the smallest rectangle which encompasses the area of the screen which
  623. needs to be redrawn. The ways to do this generally break down into two
  624. categories. The first is tracking the "damage rectangle" dynamically. In
  625. other words, as drawing operations take place on the screen you constantly
  626. compare all four corner coordinates of the affected rect against the current
  627. damage rectangle (start with a rectangle of 0 area in the center of the
  628. screen). Anytime that a coordinate falls outside the current range, the range
  629. is adjusted to encompass it. The second method involves calculating the
  630. damage rectangle at update time, by performing some comparisons against the
  631. rectangles affected by any drawing operations since the last update.
  632.  
  633. A better way to handle windowing operations, imho, is to make the windows
  634. into proactive objects. There are again two general approaches. The first is
  635. to have each window store a copy of the background it obliterates, so that it
  636. can restore that background when it changes position. The downside of this is
  637. that it cannot know about changes to that background since the background was
  638. captured. A better way is exactly how MS Windows, and most other GUIs, do it,
  639. and that is to make each window responsible for repainting itself on command.
  640.  
  641.                                                         --Mark
  642.  
  643. __________________________ Subj: Pinball Formulas __________________________
  644.  
  645. Fm: Diana Gruber/Fastgraph 72000,1642          # 371480 
  646. To: Randy @ Safari 71165,3600 (X)              Date: 08-Jun-93  12:42:06
  647.  
  648. Randy,
  649.  
  650. I don't know *all* the equations by heart! I usually look them up in a
  651. college physics book. But here are some suggestions.
  652.  
  653. The speed of the ball will be constantly changing according to the force
  654. applied. Change in speed is acceleration, Force comes from three sources: the
  655. springs, friction, and gravity. You can probably ignore friction because it
  656. will be trivial compared to the other two forces.
  657.  
  658. The equation for acceleration is:
  659.  
  660.   a=f/m
  661.  
  662. Since you don't know what the mass is, normalize it to 1. Then plug in values
  663. for f until the game 'feels' right.
  664.  
  665. Velocity is calculated in units of pixels per clock tick. The equation is:
  666.  
  667.  v = v0 + at
  668.  
  669. Position at any point in time is
  670.  
  671.  x = x0 + v[x]t + 1/2a[x]t^2
  672.  y = y0 + v[y]t + 1/2a[y]t^2
  673.  
  674. The angle you bounce off something is the same as the angle you hit it.
  675.  
  676. I always thought a pinball machine would be real fun to write. If somebody
  677. writes a good one, let me know, I know a publisher who is looking for one.
  678.  
  679. Diana
  680.  
  681. __________________________ Subj: Fixed Point Math __________________________
  682.  
  683. Fm: KGliner 70363,3672                         # 296776 
  684. To: all                                        Date: 13-Feb-93  22:29:10
  685.  
  686.     I've been going through my program code and replacing all my floating
  687. point code with 32-bit fixed point (where the upper 16 bits is the part to
  688. the left of the decimal, and the lower 16 bits is to the right), but I've run
  689. into a problem with some of the math.  Addition and subtraction are no
  690. problem-- it's just certain circumstances of multiplication and division that
  691. I'm unsure about.
  692.  
  693.   For example, say I have two floating point numbers, x=1111.1111 and y=
  694. 2222.2222.  If these were stored as 32 bit integers, then doing a calculation
  695. like x * y would create an overflow, and x div y would yield a result of
  696. zero. 
  697.  
  698.   So the question is, how do I do this and still maintain the same (or close
  699. enough) precision to the floating point calculations (and in assembly
  700. language as well, since the whole reason for using integers is to optimize
  701. for speed)? 
  702. ...........................................................................
  703.  
  704. Fm: Hans Peter Rushworth 100031,473            # 297262 
  705. To: KGliner 70363,3672                         Date: 14-Feb-93  20:47:24
  706.  
  707. Assuming you have a 386 or 486...
  708.  
  709. Multiplication first:
  710.  
  711.  MOV EAX,x
  712.  IMUL DWORD PTR y  ; 64-bit result in EDX:EAX (32 bit fraction is in EAX)
  713.  SHRD EAX,EDX,16  ; reposition binary pt, 32-bit result in EAX (16 bit fract)
  714.  
  715. Division:
  716.  
  717.  MOV EAX,x        ; These two lines load x into EDX:EAX
  718.  CDQ              ;
  719.  SHLD EDX,EAX,16  ; convert 48.16-bit value to 32.32-bit one
  720.  SHL EAX,16       ; SHLD does not effect the second operand (EAX) so repeat
  721.  IDIV DWORD PTR y  ; EAX = EDX:EAX/y (16.16-bit), EDX = EDX:EAX % y
  722.  
  723. Note: these are *signed* multiplies/divides. precision is maintained.
  724. ...........................................................................
  725.  
  726. Fm: Hans Peter Rushworth 100031,473            # 297700 
  727. To: KGliner 70363,3672 (X)                     Date: 15-Feb-93  15:22:30
  728.  
  729. Kevin,
  730.  
  731. >> [Inline assembly kludge needed]
  732.  
  733. Ok... You didn't hear it from me <g> but:
  734.  
  735. CDQ: 66 99
  736.  
  737. SHRD EAX,EDX,16 : 66 0F AC D0 10
  738.  
  739. SHLD EDX,EAX,16 : 66 0F A4 C2 10
  740.  
  741. (all in hex)
  742. ...........................................................................
  743.  
  744. Fm: KGliner 70363,3672                         # 298005 
  745. To: Hans Peter Rushworth 100031,473 (X)        Date: 16-Feb-93  01:16:13
  746.  
  747. Peter-  Thanks, that sort of worked.  That is, the divisor (in EAX) was
  748. correct, but the remainder (in EDX) wasn't.  Perhaps it needs to be shifted
  749. 16 bits left?  I'll experiment with it and see what happens, although part of
  750. the problem may just be my forcing it into inline.
  751. ...........................................................................
  752.  
  753. Fm: Chris Lampton [GAMPUB] 76711,301           # 298520 
  754. To: KGliner 70363,3672 (X)                     Date: 16-Feb-93  23:25:44
  755.  
  756. After talking with you on the phone, I think I have a clearer idea where the
  757. problem is. For your purposes, you won't need the value in EDX after the
  758. division is performed. Everything you need will be in EAX, with exactly the
  759. 16.16 precision you want. Here's how it works in the code Peter gave you:
  760.  
  761. When you start out, you have a 32-bit dividend with 16.16 precision, which
  762. we'll say looks like this in hex:
  763.  
  764. 76543210
  765.  
  766. The first instruction of Peter's code:
  767.  
  768.  MOV EAX,x
  769.  
  770. gets this value into EAX. Now we need to convert this number into a 64-bit
  771. value with 48.16 precision that spans the EAX (low 32 bits) and EDX (high 32
  772. bits) register. We do this by sign-extending EAX into EDX with the CDQ
  773. (Convert Doubleword to Quadword) instruction:
  774.  
  775.  CDQ              ;
  776.  
  777. Now our number has become
  778.  
  779. 0000000076543210
  780.  
  781. in EDX:EAX. Before we perform division, however, we have to add 16 bits more
  782. precision to the right of the decimal point, because we're going to lose
  783. those bits during division. We do this by shifting the digits of the 64-bit
  784. number in EDX:EAX 16 bits to the left. For reasons that are more easily
  785. understood if you consult a good 80386 programming manual, this requires
  786. _two_ shift instructions:
  787.  
  788.  SHLD EDX,EAX,16  ; convert 48.16-bit value to 32.32-bit one
  789.  SHL EAX,16       ; SHLD does not effect the second operand (EAX) so repeat
  790.  
  791. Now the number looks like this:
  792.  
  793. 0000765432100000
  794.  
  795. Finally we perform the division:
  796.  
  797.  IDIV DWORD PTR y  ; EAX = EDX:EAX/y (16.16-bit), EDX = EDX:EAX % y
  798.  
  799. This divides the 64-bit number in EDX:EAX by the 32-bit fixed point number at
  800. y. Because this divisor also has 16.16 precision, the division has the effect
  801. of shifting the decimal point back 16 positions to the right in the quotient,
  802. which puts us back where we started -- with a 32-bit number in the EAX
  803. register that has 16.16 precision. Don't worry about what's in EDX, just use
  804. the number in EAX as your result.
  805.  
  806. _______________________ Subj: Fixed Point Algorithms _______________________
  807.  
  808. Fm: Chris Lampton [GAMPUB] 76711,301           # 328647 
  809. To: Lutz Kretzschmar 100023,2006 (X)           Date: 07-Apr-93  12:01:00
  810.  
  811. In principle, fixed-point math is quite simple. For speed, however, it's best
  812. done with 16:16 precision on an assembly language level, at least on a 32-bit
  813. chip. The reason for limiting the code to 16:16 is that, otherwise, you'll
  814. have to jump through hoops to keep from shifting bits off the end of a
  815. register (or integer variable) and into oblivion. 
  816.  
  817. Fixed point addition and subtraction are trivial; they work just like integer
  818. addition and subtraction. You just have to be sure that the decimal points
  819. are aligned in the two numbers to be added or subtracted.
  820.  
  821. Multiplication and division are a bit trickier. Bear in mind that
  822. multiplication shifts your decimal point to the left and division shifts your
  823. decimal point to the right. Thus, you must combine the multiplication or
  824. division with a shift to make sure the decimal point ends up where you want
  825. it. (Despite the term "fixed point," the decimal point actually does a lot of
  826. floating around. You have to _work_ to keep it fixed.) With multiplication,
  827. you perform the shift after the operation. With division, you usually perform
  828. it _before_ the operation. The decimal points in the multiplier and
  829. multiplicand (or divisor and dividend) do not need to be aligned, but you do
  830. need to know where the decimal point is going to end up. Here's a simple
  831. rule: After multiplication, the number of digits following the decimal in the
  832. result will be the number of digits following the decimal in the multiplier
  833. PLUS the number of digits following the decimal in the multiplicand, like
  834. this: 
  835.  
  836.       aaaaaaaaaaaa.aaaa
  837.     x bbbbbbbbbbbb.bbbb
  838.     --------------------
  839.   cccccccccccc.cccccccc
  840.  
  841. Note that this is identical to the long multiplication procedure you learned
  842. in school, decimal placement and all.
  843.  
  844. After division, the number of digits following the decimal in the result will
  845. be the number of digits following the decimal in the dividend MINUS the
  846. number of digits following the decimal in the divisor, like this: 
  847.  
  848.    aaaaaaaaaaaa.aaaa
  849.  % bbbbbbbbbbbbbb.bb
  850.  -------------------
  851.          cccccccc.cc
  852.  
  853. This is why you must shift to the right _before_ division, so that you don't
  854. lose any digits to the right of the decimal point.
  855.  
  856. Here's a simple C demonstration of fixed point multiplication with 24:8
  857. precision:
  858.  
  859.   long multiplier,multiplicand,product;
  860.   product = multiplier * multiplicand >> 8;
  861.  
  862. And here's a demonstration of fixed point division:
  863.  
  864.   long divisor,dividend,quotient;
  865.   quotient = (dividend << 8) / divisor;
  866.  
  867. Note that the leftmost eight digits of the result are lost in both cases.
  868. Thus, although the official precision of these fixed point variables is 24:8,
  869. the _effective_ precision is only 8:8 -- and we're using 32-bit _longs_ here!
  870. That's why fixed point is better performed in 80386 assembly language. The
  871. 386 32-bit multiplication instruction, while restricted to 32-bit operands,
  872. produces a 64-bit result. Thus, while the leftmost digits may be shifted out
  873. of the EAX register, they are preserved in the EDX register, from whence they
  874. can be shifted back into EAX. And the 386 also allows a 64-bit dividend in
  875. division instructions. Pete Rushworth posted some excellent code a while back
  876. for 386 fixed point. If he doesn't jump in here and post it again, I'll see
  877. if I can dig it out, assuming you're interested in working with 386
  878. assembler. But bear in mind that these routines are still restricted to 16:16
  879. precision. If you really need 32:32 precision, you've got a lot of work ahead
  880. of you, unless you're working on a 64-bit CPU! 
  881.  
  882. --Chris
  883.  
  884. p.s. Sorry I can't point you toward any books, but I've never been able to
  885. find any that discuss it. I talk about this briefly in my book Flights of
  886. Fantasy, but I don't say anything I haven't told you in this message.
  887. ........................................................................... 
  888.  
  889. Fm: Chris Lampton [GAMPUB] 76711,301           # 328660 
  890. To: Lutz Kretzschmar 100023,2006 (X)           Date: 07-Apr-93  12:22:42
  891.  
  892. Whoops, in that last message where I refer to shifting RIGHT before division,
  893. change that to shifting LEFT before division. I've always been a bit
  894. dyslexic.... <g>
  895.  
  896. --Chris
  897. ...........................................................................
  898.  
  899. Fm: KGliner 70363,3672                         # 329382 
  900. To: Lutz Kretzschmar 100023,2006               Date: 08-Apr-93  18:25:32
  901.  
  902. Ok, this is straight from my code:
  903.  
  904.  Multiply a * b:                  Division:
  905.  
  906.    mov ebx,[a]                   mov eax,[dividend]
  907.    mov eax,[b]                   mov ebx,[divisor]
  908.    mul ebx                       xor edx,edx
  909.    shr eax,16                    div ebx
  910.    shl edx,16                    mov ecx,eax
  911.    mov dx,ax                     mov eax,0ffffh
  912.    mov [result],edx              div ebx
  913.                                  shr eax,16
  914.                                  sal ecx,16
  915.                                  mov cx,ax
  916.                                  mov [result],ecx
  917.  
  918.    Both these work for positive numbers.  You might be able to speed up the
  919. multiplication, and I know for sure that the division could be more
  920. efficient. For one thing, there should be a way to do it with only one div
  921. instruction, but I never could get it work that way.  If you find a way to
  922. optimize it, let me know.
  923.  
  924.    Oh yeah, Randy (at Safari) helped me hack out the division routine,
  925. although he may not want credit for that<g>.  I actually had quite a number
  926. of solutions when I posted a similar question about a month or two ago. This
  927. is the only one I could get to work though.
  928.  
  929.    Kevin
  930.  
  931. ___________________________ Subj: Fractal Terrain ___________________________
  932.  
  933. Fm: Hans Peter Rushworth 100031,473            # 213126 
  934. To: Mark Betz/GD SL 76605,2346 (X)             Date: 14-Sep-92  22:52:38
  935.  
  936. If you use a "plasma" type fractal for generating mountains, you can improve
  937. the "flatness" between the mountains and the sea by cubing the altitudes of
  938. the points and then dividing by a constant value. If the result is too
  939. "craggy" you can flatten the peaks using a square root (or similar) function
  940. in more or less the same way. The problem with this method is determining a
  941. realistic course for rivers, and man-made constructions like roads.
  942.  
  943. There is also a rule (I think it's called Zipfs (sp?) law) that relates to
  944. the distribution of peak altitudes, that might be worth looking into.
  945.  
  946. Peter.
  947. ...........................................................................
  948.  
  949. Fm: Mark 'SAM' Baker 100025,444                # 213312 
  950. To: Mark Betz/GD SL 76605,2346 (X)             Date: 15-Sep-92  14:01:49
  951.  
  952. Fractals are an excellent method of generating pseudo-random terrain.
  953. Plasma clouds are probably the easiest to use; but their are some algorithms
  954. in either 'The Beauty of Fractals' or 'The Mathematics of Fractals' that are
  955. specific to developing continental map simulacrums. For semi-realistic
  956. random-landscapes, fractals are excellent.
  957. ...........................................................................
  958.  
  959. Fm: John Burkhard 71044,3263                   # 281177 
  960. To: John W. Ratcliff 70253,3237 (X)            Date: 18-Jan-93  17:00:33
  961.  
  962. Along the lines of fractals...  Even with an FPU, computation times for
  963. generating the Mandlebrot set over the range -2,-2 .. 2,2 is *very* time
  964. consuming, especially at the resolution you're talking about.
  965.  
  966. A couple of years ago, when I got hooked on fractals, a friend of mine
  967. suggested an interesting approach to plotting the set.  Given that the
  968. points within the set are relatively uninteresting (and take the longest
  969. amount of time to compute), his approach concentrated on the points outside
  970. the set first, and then tackled the points within the set.
  971.  
  972. He repeatedly subdivided the screen area into four equal sized windows, and
  973. calculated the Mandlebrot function for the center point in each sub region.
  974. If the point calculated was within the set, he added that region to a queue
  975. for later processing; otherwise, he recursively subsidived each of the sub
  976. regions, and so on until the region was 1 pixel big.  Once the function
  977. backed all the way out, he grabbed the next region from the queue and
  978. continued.
  979.  
  980. In pseudo code:
  981.  
  982. add entire_screen_region to region_queue
  983. while region_queue is not empty
  984.    process_region with head of region queue
  985. endwhile
  986.  
  987.  
  988. process_region::
  989.    if region is 1 pixel big
  990.       computer mandlebrot value
  991.       plot the appropriate color based upon result
  992.       return to caller
  993.    else
  994.       subdivide region into 4 quadrants
  995.       for each quadrant
  996.          compute mandlebrot of center point
  997.          if result is within the mandlebrot set
  998.             add quadrant to region_queue
  999.             return to caller
  1000.          else
  1001.             fill region with appropriate color, based upon result
  1002.             process_region with quadrant
  1003.          endif
  1004.       next
  1005.    endif
  1006.  
  1007. At least I think that's pretty much how it went.  One interesting side note
  1008. about the above:  While it does result in some extra computations, for the
  1009. most part it's not that bad.  And since the colored areas are filled in
  1010. first, and since there's almost constant screen activity, it *appears* to be
  1011. faster than the brute force method of scanning line by line.
  1012.  
  1013. -jb
  1014. ...........................................................................
  1015.  
  1016. Fm: Chris Lampton [GAMPUB] 76711,301           # 330470 
  1017. To: Ralph Wirthlin 76247,715 (X)               Date: 10-Apr-93  12:12:14
  1018.  
  1019. I fiddled around with some code for generating fractal scenery objects while
  1020. writing FLIGHTS OF FANTASY, but didn't include the code in the book because
  1021. of technical problems involved in translating the fractal data to the data
  1022. format I used for storing objects. (I do discuss it in theory, however, with
  1023. a simple demonstration program.) Actually, there are probably an infinite
  1024. number of ways to generate fractal landscapes, most of which I've never
  1025. attempted (and probably haven't imagined). Most, however, are based on the
  1026. same premise: Start with a simple shape and break it recursively into
  1027. segments (breaking the segments into segments and so forth, until you've
  1028. reached the desired recursive depth). Use a small (or not so small, depending
  1029. how "rough" you want to the landscape to look) random factor to perturb, or
  1030. "skew", each subsegment from the orientation of the main segment. For
  1031. instance, a coastline (or river or highway) could start out as a straight
  1032. line, be broken into two skewed segments (not _exactly_ in the middle), which
  1033. would each in turn be broken recursively into two skewed segments, and so
  1034. forth, until sufficient "crookedness" has been achieved. By using the same
  1035. random number seed each time, the coastline can be made reproducible, so that
  1036. it will always look the same when the viewer returns to it. This can be done
  1037. either in real time (if your code is fast enough) or to generate static data
  1038. that can be stored in the scenery database (if you have room for it).
  1039.  
  1040. The method that I was tinkering with in FOF (but wound up not using) would
  1041. have generated fractal mountains. The basic technique is this: Start out with
  1042. a pyramid, i.e. a mountain made out of four triangles with a rectangular
  1043. base. Break each triangle into four smaller triangles, like this:
  1044.  
  1045.                            *
  1046.                          *   *
  1047.                        *       *
  1048.                      *           *
  1049.                    *               *
  1050.                  *                   *
  1051.                * * * * * * * * * * * * *
  1052.              *   *                   *   *
  1053.            *       *               *       *
  1054.          *           *           *           *
  1055.        *               *       *               *
  1056.      *                   *   *                   *
  1057.    * * * * * * * * * * * * * * * * * * * * * * * * *
  1058.  
  1059. Note that this involves splitting each edge of the original triangle into two
  1060. edges. This should be done with a random factor so that the break rarely
  1061. occurs at the exact center of an edge and the break points should be randomly
  1062. perturbed from the original line by a few units in the x and/or y directions
  1063. to make the new edges slightly (or not-so-slightly) skewed. This gives the
  1064. divided triangle a jagged, rocky look (which it does not have in my simple
  1065. ASCII illustration). Then repeat this process recursively on all four smaller
  1066. triangles, until you have as much detail as you need (or can handle). Do this
  1067. with each triangular face of the original pyramid and you have a mountain.
  1068. (One of the trickiest parts is making sure that all the mountain faces meet
  1069. at common vertices.) Obviously you don't start drawing (or storing) any of
  1070. this until you reach the lowest level of recursion; intermediate data should
  1071. be discarded. 
  1072.  
  1073. I realize this is a somewhat simplistic explanation of fractal scenery
  1074. generation, and probably doesn't begin to answer the questions that you have,
  1075. but it establishes the principles. I plan to research this topic in greater
  1076. detail (because I still have a lot of questions about it too). I'll let you
  1077. know what I find.
  1078.  
  1079. --Chris
  1080. ...........................................................................
  1081.  
  1082. Fm: Chris Lampton [GAMPUB] 76711,301           # 330906 
  1083. To: Mitchell Waite 75146,3515 (X)              Date: 10-Apr-93  22:51:28
  1084.  
  1085. As a matter of fact, there's been a lot of serious talk around here about how
  1086. COMANCHE: MAXIMUM OVERKILL works. The present technique does _not_ seem to
  1087. use fractals. I'm not really giving away any secrets (at least among this
  1088. crowd) if I tell you that the NovaLogic programmers maintain a 2-dimensional
  1089. integer array representing the terrain, where each element of the array
  1090. represents the height of the corresponding piece of terrain above some fixed
  1091. level. (Additional information, such as terrain color, may also be contained
  1092. in the array elements.) They then apparently use a technique known as
  1093. raycasting (a kind of highly simplified raytracing) to establish how these
  1094. height fields would appear from the viewer's position. This is hard to
  1095. explain, but...imagine that the viewport on the display is divided from left
  1096. to right into vertical columns one pixel in width, each stretching from the
  1097. top to the bottom of the viewport. (There would be 320 such columns in a
  1098. full-screen mode 13h viewport.) A single ray (basically, a straight line) is
  1099. "cast" from the viewer's position for each of these vertical columns. Each
  1100. time the ray passes over a terrain element (which the COMANCHE developers
  1101. apparently refer to as "voxels," though that's not how that term is
  1102. traditionally used), a vertical segment of the current screen column
  1103. representing the (rotated and perspective-projected) difference in height
  1104. between that voxel and the previous voxel passed over by the ray is painted
  1105. in the (light-sourced?) voxel color. Magically, this gives the appearance of
  1106. a three-dimensional landscape. If you look closely at the COMANCHE screen,
  1107. you'll see that it appears to be made out of vertically elongated pixels,
  1108. which change their elongation as you move relative to the terrain. 
  1109.  
  1110. That's a pretty rough sketch of the technique, of course. It's a very clever
  1111. -- and very fast -- method of drawing hyper-realistic terrain. The main
  1112. problem at present is that the terrain array requires a lot of storage,
  1113. limiting the terrain size and resolution. However, if someone found a way to
  1114. combine it with fractal terrain generation techniques, it might be possible
  1115. to generate nearly infinite amounts of high-resolution, stunningly-realistic
  1116. terrain. I'm itching for a chance to experiment with these techniques and see
  1117. if I can get them to work. And I'd love to write a book (or part of a book)
  1118. about the results. 
  1119.  
  1120. I've played with the FRACTINT plasma fractals a bit, with some very
  1121. interesting results. Wonder if there's a way to get _that_ sort_ of thing
  1122. working in real time? It's a completely different technique than that used in
  1123. COMANCHE, but probably more versatile and with more long-range possibilities.
  1124.  
  1125.  --Chris
  1126. ...........................................................................
  1127.  
  1128. Fm: John Dlugosz [ViewPoint] 70007,4657        # 330491 
  1129. To: Ralph Wirthlin 76247,715 (X)               Date: 10-Apr-93  12:28:01
  1130.  
  1131. Well, here is a simple example.  It uses midpoint subdivision of triangles.
  1132.  
  1133.  void z (pair p, pair p1, pair p2, int n)
  1134.  {
  1135.  if (A[p.x][p.y] != 0) return;  //already covered this one
  1136.  fpnum val= A[p1.x][p1.y] + A[p2.x][p2.y];
  1137.  val += random (n);
  1138.  A[p.x][p.y]= val/2;
  1139.  // show what is happening
  1140.  plot (p);
  1141.  }
  1142.  
  1143.  /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  1144.  
  1145.  void compute (pair p, int n)
  1146.  {
  1147.  const half_n= n/2;
  1148.  pair right= point (p.x+n, p.y);
  1149.  pair down= point (p.x, p.y+n);
  1150.  //find midpoints
  1151.  int midx= p.x+half_n;
  1152.  int midy= p.y+half_n;
  1153.  pair pr= point (midx, p.y);
  1154.  pair pd= point (p.x, midy);
  1155.  pair rd= point (midx, midy);
  1156.  // find z values
  1157.  z (pr, p,right, n);
  1158.  z (pd, p,down, n);
  1159.  z (rd, right,down, n);
  1160.  if (n != 1 && n != -1) {
  1161.     compute (p, half_n);
  1162.     compute (pr, half_n);
  1163.     compute (pd, half_n);
  1164.     compute (rd, -half_n);
  1165.     }
  1166.  }
  1167.  
  1168.  /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  1169.  
  1170.  int main (int argc, char* argv[])
  1171.  {
  1172.  if (argc > 1) seed= atol(argv[1]);
  1173.  setup_A();
  1174.  activate (d);
  1175.  setup_d();
  1176.  show_scale();
  1177.  compute (point(0,0), 128);
  1178.  compute (point(128,128), -128);
  1179.  saveimage();
  1180.  key::get();
  1181.  return 0;
  1182.  }
  1183.  
  1184. ________________________ Subj: Random Bit Generator ________________________
  1185.  
  1186. Fm: Serge Mathieu 71035,2771                   # 250051 
  1187. To: Mark Betz/Ass't SysOp 76605,2346 (X)       Date: 23-Nov-92  22:22:45
  1188.  
  1189. Mark,
  1190.  
  1191. I'm not sure if this is the right way to code it in asm...
  1192.  
  1193. _PSEUDO-RANDOM SEQUENCE GENERATOR FOR 32-BIT CPUs_ by Bruce Schneier (DrDOBBS
  1194. Journal)
  1195.  
  1196. int RANDOM ()  {
  1197.     static unsigned long register; /*Register must be unsigned so right
  1198.                                      shift works properly.*/
  1199.     /*Register should be initialized with some random value.*/
  1200.     register = ((((register >> 31) /*Shift the 32nd bit to the first bit*/
  1201.                ^ (register >> 6)   /*XOR it with the seventh bit*/
  1202.                ^ (register >> 4)   /*XOR it with the fifth bit*/
  1203.                ^ (register >> 2)   /*XOR it with the third bit*/
  1204.                ^ (register >> 1)   /*XOR it with the second bit*/
  1205.                ^ register)         /*and XOR it with the first bit.*/
  1206.                & 0x0000001)        /*Strip all the other bits off and*/
  1207.                <<31)               /*move it back to the 32nd bit.*/
  1208.                | (register >> 1);  /*Or with the register shifted right.*/
  1209.     return register & 0x00000001;  /*Return the first bit.*/ }
  1210.  
  1211. BASM (TP6 built-in asm, 286 code) (note:bits 1 to 32) for 2 x 16 bit
  1212. registers:
  1213.  
  1214. Seed in DX:AX cl contains number of bits to generate ch is random
  1215. number (maximum 8 bits) bx used to xor bit 32 with bits 7,5,3,2,1
  1216.  
  1217.         mov cl,number_of_bits_needed
  1218.         xor ch,ch
  1219. @Bit_Loop:
  1220.         mov bh,dh   {bit 32}
  1221.         mov bl,al   {bits 7,5,3,2,1}
  1222.         shl bl,1    {bit 7 to upper bit}
  1223.         xor bh,bl   {xor upper bits and don't care about others}
  1224.         shl bl,2    {bit 5}
  1225.         xor bh,bl
  1226.         shl bl,2    {bit 3}
  1227.         xor bh,bl
  1228.         shl bl,1    {bit 2}
  1229.         xor bh,bl
  1230.         shl bl,1    {bit 1}
  1231.         xor bh,bl
  1232.         shr dx,1    {shift seed 16 bits}
  1233.         rcr ax,1    {plus 16 bits for 32 bits}
  1234.         rcl ch,1    {ch builds random number from bit 1}
  1235.         and bh,10000000b   {bit 8}
  1236.         or dh,bh    {to update bit 32}
  1237.         dec cl
  1238.         jnz @Bit_Loop
  1239.  
  1240. Serge Mathieu
  1241. ...........................................................................
  1242.  
  1243. Fm: Hans Peter Rushworth 100031,473            # 206819 
  1244. To: Sarwan Narine 76675,164 (X)                Date: 31-Aug-92  11:40:45
  1245.  
  1246. The most common and fast method is the "Linear Congruential Generator":
  1247.  
  1248. X(n+1) = ((a*X(n))+c) mod m. where a,c,m are specially chosen constants.
  1249.  
  1250. Knuth gives an in-depth analysis of this complex topic in "Seminumerical
  1251. Algorithms".
  1252.  
  1253. Another method that is useful for binary decision making purposes (ie random
  1254. YES/NO decisions), is based on data scrambling and encryption schemes. These
  1255. methods employ a shift register with the output data element being the
  1256. exclusive or of selected bits in the register. The output data bit is fed
  1257. back into the input of the register, and each clock produces a pseudo random
  1258. bit. The choice of which bits to feedback and the initial value of the
  1259. register is important in order to produce a long non-repeating sequence. Most
  1260. Communications Theory textbooks describe this method when applied to 
  1261.  
  1262. Peter.
  1263.  
  1264. ________________________ Subj: Point inside polygon? ________________________
  1265.  
  1266. Fm: Tim Koffley 70334,16                       # 379820
  1267. To: all                                        Date: 20-Jun-93  12:39:18
  1268.  
  1269. Ok geometry fans, anyone got a quick/easy algorithm for determining if a
  1270. point is inside a *strictly convex* polygon?  I'm translating a board game to
  1271. Windows (via Visual Basic) and I'm trying to detect when the mouse moves over
  1272. a "room" on the board.  The rooms are n-vertex convex polygons.  I'm looking
  1273. for something quick (and possibly dirty) as the sucker is called anytime the
  1274. mouse moves (and it *is* Basic). 
  1275. Thanks in advance,
  1276.    -tk
  1277. ...........................................................................
  1278.  
  1279. Fm: Patrick Reilly 71333,2764                  # 380001 
  1280. To: Tim Koffley 70334,16 (X)                   Date: 20-Jun-93  16:59:01
  1281.  
  1282. Tim,
  1283.   All I can think of is to walk through the line segments that make up the
  1284. polygon and find all that intersect the x coord of the point and the y coord
  1285. of the point; if you end up with at least 4, with at least one above, one
  1286. below, one left and one right, its in the polygon.
  1287.         -Pat-
  1288. ...........................................................................
  1289.  
  1290. Fm: Tim Koffley 70334,16                       # 380078 
  1291. To: Patrick Reilly 71333,2764 (X)              Date: 20-Jun-93  18:21:26
  1292.  
  1293. >All I can think of is to walk through the line segments that make up the
  1294. polygon and find all >that intersect the x coord of the point and the y coord
  1295. of the point; if you end up with at least >4, with at least one above, one
  1296. below, one left and one right, its in the polygon.
  1297.  
  1298. I kinda understand what you're saying.  But...
  1299. a) what about triangular rooms
  1300. b) I'm not sure what you mean by "above, below, left, right" and how you
  1301. determine a           segment's "aboveness" or otherwise...
  1302.  
  1303. If you feel like it, walk me through this case.....
  1304.  
  1305.   |\
  1306.   |  \
  1307.   |    \ o  <----- the point in question
  1308.   |      \
  1309.   |        \
  1310.   ------------
  1311.  
  1312.   If that works, show with the point inside.
  1313.  
  1314.   thanks,
  1315.   -tk
  1316. ...........................................................................
  1317.  
  1318. Fm: Patrick Reilly 71333,2764                  # 380415 
  1319. To: Tim Koffley 70334,16                       Date: 21-Jun-93  01:16:47
  1320.  
  1321. Tim,
  1322.   For your triangle (or any other n-gon with vertices >= 3):
  1323.  
  1324.   |\
  1325.   |  \
  1326.   |    X o  <----- the point in question
  1327.   |      X
  1328.   |        \
  1329.   -------X----
  1330.  The "X" indicates where a line segment from the triangle is intersected by
  1331. the x, and y, coordinates of the point. It has 1 "X" to its left, and two
  1332. "X"s below - the point is not contained within the triangle.
  1333.  
  1334.   |\
  1335.   |  X
  1336.   X  o X   <----- the point in question
  1337.   |      \
  1338.   |        \
  1339.   ---X--------
  1340.  
  1341. There is now an X in each direction from the point (one left, one right, one
  1342. above and one below) - the point is contained in the triangle.
  1343.  
  1344.   |\
  1345.   |  \
  1346.   X    o  <----- the point in question
  1347.   |      \
  1348.   |        \
  1349.   -----X------
  1350.  The point IS one of the intersections - you have to decide whether it should
  1351. be considered within or without the triangle.
  1352.  
  1353.   This will work with any convex 2D polygon. Algorithm:
  1354.         Let point = X,Y.
  1355.         Let N be the number of vertices in the polygon.
  1356.         Left left = top = right = bottom = False.
  1357.         For each vertex V in the polygon do
  1358.           Let VN be the next vertex from V (VN of V(N-1) is V(0))
  1359.           <special case>
  1360.           If VN.x == V.x and VN.x == X then
  1361.             If (VN.y <= Y and V.y >= Y) or (VN.y >= Y and V.y <= Y) then
  1362.               <lies on a vertical line - immediately pass or fail>
  1363.           <special case>
  1364.           Else If VN.y == V.y and VN.y == Y then
  1365.             If (VN.x <= X and V.x >= X) or (VN.x >= X and V.x <= X) then
  1366.               <lies on a horizontal line - immediately pass or fail>
  1367.           <line is neither vertical nor horizontal>
  1368.           Else
  1369.             r = (X-V.x)*(VN.y-V.y)/(VN.x-V.x) + V.y
  1370.             If r < Y then Top = True;
  1371.             Else if r > Y then Bottom = True
  1372.             Else  <pass/fail - point lies on the line>
  1373.             r = (Y-V.y)*(VN.x-V.x)/(VN.y-V.y) + V.x
  1374.             If r < X then Left = True
  1375.             Else If r > X then Right = True
  1376.             Else <pass/fail - point lies on the line>
  1377.  
  1378.         If Top = True and Bottom = True and Left = True and Right = True
  1379.           Pass.
  1380.         Else
  1381.           Fail.
  1382.  
  1383.         -Pat-
  1384. ...........................................................................
  1385.  
  1386. Fm: Chris Lampton [GAMPUB] 76711,301           # 380007 
  1387. To: Tim Koffley 70334,16 (X)                   Date: 20-Jun-93  17:07:55
  1388.  
  1389. Here's a quote from Alan Watt's FUNDAMENTALS OF THREE-DIMENSIONAL computer
  1390. graphics: "The sum of the angles between lines drawn from the point to each
  1391. vertex is 360 degrees if the point is inside the polygon, but not if the
  1392. point lies outside."
  1393.  
  1394. That sounds like a lot of work to put yourself and your program through,
  1395. especially if the code is to be executed every time the mouse moves. The
  1396. quickest and dirtiest alternative I can think of would trade off a big chunk
  1397. of memory for speed: Set aside a byte array (or the closest VB equivalent) in
  1398. which each element corresponds to a pixel location on the game board and
  1399. contains the number of the room of which that pixel is part (or a value
  1400. indicating that it's not part of a room). For the cost of an array index, you
  1401. can know whether the mouse is inside a room and which room it is inside.
  1402.  
  1403. --Chris
  1404. ...........................................................................
  1405.  
  1406. Fm: Tim Koffley 70334,16                       # 380079 
  1407. To: Chris Lampton [GAMPUB] 76711,301 (X)       Date: 20-Jun-93  18:21:32
  1408.  
  1409. >graphics: "The sum of the angles between lines drawn from the point to each
  1410. vertex is 360 >degrees if the point is inside the polygon, but not if the
  1411. point lies outside."
  1412.  
  1413. Thanks for the info.  Of course, I *knew* about that property of a convex
  1414. polygon, I just...er....FORGOT OK?  <g>.  That might not be *too* bad cuz
  1415. most rooms are either 4 or 5 vertices and I've split the board into four
  1416. regions to narrow/speed the search a bit.  *Plus* I now realize I can
  1417. discount positions of a certain color (talk about digging!).
  1418.  
  1419. >can think of would trade off a big chunk of memory for speed: Set aside a
  1420. byte array in which >each element corresponds to a pixel location on the game
  1421. board
  1422.  
  1423. Your alternate idea is fine BUT, I'm trying to keep with Windows' silly
  1424. measurement system of "twips" for other practical reasons and, besides, my
  1425. board bit map is roughly 1000x800 pixels!
  1426.  
  1427.   -tk
  1428. ...........................................................................
  1429.  
  1430. Fm: Chris Lampton [GAMPUB] 76711,301           # 380099 
  1431. To: Tim Koffley 70334,16 (X)                   Date: 20-Jun-93  19:02:28
  1432.  
  1433. >my board bit map is roughly 1000x800 pixels!
  1434.  
  1435. Hey, that would only be a 782 kilobyte array! Cheap at the price! <g>
  1436.  
  1437. Heck, if you can use pixel color to trivially dismiss positions -- use it!
  1438. The ideal would be to use a different interior palette for every polygon, so
  1439. that the board bitmap itself could be used to easily differentiate polygons.
  1440. Of course, that's a bit of a kludge, but I'm always on the lookout for a
  1441. useful kludge. ;-)
  1442.  
  1443. --Chris
  1444. ...........................................................................
  1445.  
  1446. Fm: Jez San @ Argonaut 72247,3661              # 380148 
  1447. To: Tim Koffley 70334,16 (X)                   Date: 20-Jun-93  19:48:40
  1448.  
  1449. tk -
  1450.  
  1451. use a bounding rectangle that totally contains your polygon to do trivial
  1452. checking to see which area of the screen the mouse pointer is in, ie: to
  1453. within 1 or 2 possible polygons.
  1454.  
  1455. Then you can do a simple plane equation check for each edge of the polygon to
  1456. ensure that the point of the mouse pointer is on the correct side of each
  1457. plane (ie: checking that the normal to the plane always points away from the
  1458. point, or something similar).
  1459.  
  1460. -- Jez.
  1461. ...........................................................................
  1462.  
  1463. Fm: David Laturner 100031,1127                 # 380461 
  1464. To: Tim Koffley 70334,16                       Date: 21-Jun-93  06:03:45
  1465.  
  1466.     How about a sparse array?
  1467.     For each pixel row in the game board, store the columns where rooms start
  1468. and end ( or vice versa ). Then your check will be a simple linear search
  1469. along the row the mouse is in.
  1470.  
  1471.        Dave.
  1472. ...........................................................................
  1473.  
  1474. Fm: Tim Koffley 70334,16                       # 381110 
  1475. To: Patrick Reilly 71333,2764 (X)              Date: 21-Jun-93  22:32:01
  1476.  
  1477. Thank a lot for the reply.  I now understand what you're talking about.  I'm
  1478. currently trying the "Total interior angles from the point = 360" method.
  1479. It's ok for now but I might have to try something different later.  Thanks
  1480. again!
  1481.  
  1482.    -tk
  1483. ...........................................................................
  1484.  
  1485. Fm: Tim Koffley 70334,16                       # 381117 
  1486. To: David Laturner 100031,1127 (X)             Date: 21-Jun-93  22:33:38
  1487.  
  1488. >For each pixel row in the game board, store the columns where rooms start
  1489. and end ( or vice >versa ). Then your check will be a simple linear search
  1490. along the row the mouse is in.
  1491.  
  1492. Another fine idea!  Thanks...
  1493.  
  1494.   -tk
  1495. ...........................................................................
  1496.  
  1497.  
  1498.